package srdb.migration.dbhandler.sqlserver;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;

import srdb.migration.MigrationToolkit;
import srdb.migration.Utility;
import srdb.migration.common.IMTKConnection;
import srdb.migration.common.MTKConstants;
import srdb.migration.common.MTKMetaData;
import srdb.migration.common.MTKConstants.DATABASE_TYPE;
import srdb.migration.common.MTKConstants.TABLE_CONSTRAINT_TYPE;
import srdb.migration.schema.metadata.Column;
import srdb.migration.schema.metadata.Constraint;
import srdb.migration.schema.metadata.ConstraintList;
import srdb.migration.schema.metadata.Function;
import srdb.migration.schema.metadata.FunctionList;
import srdb.migration.schema.metadata.Index;
import srdb.migration.schema.metadata.IndexList;
import srdb.migration.schema.metadata.Procedure;
import srdb.migration.schema.metadata.ProcedureList;
import srdb.migration.schema.metadata.Schema;
import srdb.migration.schema.metadata.Synonym;
import srdb.migration.schema.metadata.Table;
import srdb.migration.schema.metadata.Trigger;
import srdb.migration.schema.metadata.View;

public class MetaData extends MTKMetaData {
	public static String SQL_STATEMENT_DELIMITER = "\n;";

	private IMTKConnection conn = null;
	private DatabaseMetaData metaData = null;

	private String getTableColumnsStr = "";
	private PreparedStatement getTableColumns = null;

	private String commaSepViewNames = null;
	private String commaSepTableNames = null;

	protected PreparedStatement psConsts = null;
	protected final String sqlConsts = "SELECT OBJECT_NAME(OBJECT_ID) AS NameofConstraint, type AS ConstraintType FROM sys.objects WHERE type_desc LIKE '%CONSTRAINT'  and SCHEMA_NAME(schema_id) = ? and OBJECT_NAME(parent_object_id) = ? ";

	protected PreparedStatement psIndexesDefs = null;
	protected final String sqlIndexesDefs = "select I.name as IndexName, I.type_desc as IndexType  from sys.tables as T inner  join sys.indexes as I on T.[object_id] = I.[object_id]  inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]  inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]  inner join sys.objects as so on t.object_id = so.object_id and I.object_id = T.object_id  where SCHEMA_NAME(so.schema_id) = ?  and   so.name = ? ";

	protected HashMap<String, ArrayList> mapTableIndexesDefs = new HashMap();

	public MetaData(IMTKConnection conn) throws Exception {
		this.conn = conn;

		if (this.conn != null) {
			this.dbConn = conn.getConnection();
			this.metaData = this.dbConn.getMetaData();
		}
	}

	public MetaData(IMTKConnection conn, String targetSchemaName)
			throws Exception {
		this.conn = conn;

		if (this.conn != null) {
			this.dbConn = conn.getConnection();
			this.metaData = this.dbConn.getMetaData();
		}

		this.targetSchemaName = targetSchemaName;
	}

	protected void initTableStatement(String commaSepTableNames)
			throws SQLException {
		this.getTablesStr = "select TABLE_NAME from information_schema.tables where TABLE_NAME NOT IN ('sysconstraints', 'syssegments', 'dtproperties', 'sysdiagrams') AND table_catalog = ? AND table_schema = ? AND table_type = ?";

		this.getTables = this.dbConn.prepareStatement(this.getTablesStr);
		this.commaSepTableNames = removeSingleQuotes(commaSepTableNames);
	}

	public void getTables(String commaSepTableNames, boolean importViewAsTable)
			throws SQLException {
		super.getTables(removeSingleQuotes(commaSepTableNames),
				importViewAsTable);

		if (importViewAsTable) {
			initViewStatement(commaSepTableNames);
			getViewsAsTables();
		}
	}

	private void getViewsAsTables() throws SQLException {
		writeLog("Getting View Definitions");
		if ((this.commaSepViewNames != null)
				&& (this.commaSepViewNames.trim().length() > 0)) {
			String[] viewNames = this.commaSepViewNames.split(",");
			ResultSet rs = null;
			try {
				this.getTables.setString(1, this.dbConn.getCatalog());
				this.getTables.setString(2, this.schema.getName());
				this.getTables.setString(3, "VIEW");
				rs = this.getTables.executeQuery();
				if (rs != null) {
					Table table = null;
					while (rs.next()) {
						if (Arrays.binarySearch(viewNames, rs.getString(1)) < 0)
							continue;
						table = getTable(rs.getString(1));
						if (table != null)
							this.schema.addTable(table);
					}
				}
			} catch (SQLException exp) {
				throw processException(exp);
			} finally {
				if (rs != null)
					rs.close();
			}
		}
	}

	protected void getTables() throws SQLException {
		writeLog("Getting Table Definitions");
		Table table = null;

		if ((this.commaSepTableNames != null)
				&& (this.commaSepTableNames.length() > 0)) {
			String[] tableNames = this.commaSepTableNames.split(",");
			for (String name : tableNames) {
				table = getTable(name);
				if (table != null)
					this.schema.addTable(table);
			}
		} else {
			ResultSet rs = null;
			try {
				this.getTables.setString(1, this.dbConn.getCatalog());
				this.getTables.setString(2, this.schema.getName());
				this.getTables.setString(3, "BASE TABLE");
				rs = this.getTables.executeQuery();
				if (rs != null)
					while (rs.next()) {
						String tableName = rs.getString(1).toLowerCase();
						table = getTable(tableName);
						if (table != null)
							this.schema.addTable(table);
					}
			} catch (SQLException exp) {
				throw processException(exp);
			} finally {
				if (rs != null)
					rs.close();
			}
		}
	}

	protected void initColumnStatement() throws SQLException {
		if (isVersion2005OrGreater()) {
			this.getTableColumnsStr = "SELECT cols.name AS COLUMN_NAME, types.name AS TYPE_NAME, CASE cols.precision WHEN 0 THEN cols.max_length ELSE cols.precision END AS COLUMN_SIZE, cols.scale AS DECIMAL_DIGITS, props.text AS REMARKS, CASE cols.is_nullable WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' END AS IS_NULLABLE, defvalue.text AS COLUMN_DEF, cols.is_identity FROM sys.columns cols LEFT OUTER JOIN syscomments props ON (cols.object_id=props.id AND cols.column_id=props.colid) LEFT OUTER JOIN syscomments defvalue ON (cols.default_object_id = defvalue.id), sys.types types WHERE cols.object_id=object_id(?) AND cols.user_type_id=types.user_type_id ORDER BY cols.column_id";
		} else {
			this.getTableColumnsStr = "SELECT cols.name AS COLUMN_NAME, types.name AS TYPE_NAME, CASE cols.xprec WHEN 0 THEN cols.length ELSE cols.xprec END AS COLUMN_SIZE, cols.xscale AS DECIMAL_DIGITS, props.value AS REMARKS, CASE cols.isnullable WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' END AS IS_NULLABLE, defvalue.text AS COLUMN_DEF, CASE columnproperty(cols.id,cols.name,'IsIdentity') WHEN 1 THEN 'YES' ELSE 'NO' END AS is_identity FROM syscolumns cols LEFT OUTER JOIN sysproperties props ON (cols.id=props.id AND cols.colid=props.smallid) LEFT OUTER JOIN syscomments defvalue ON (cols.cdefault = defvalue.id) , systypes types WHERE cols.id=object_id(?) AND cols.xusertype=types.xusertype ORDER BY cols.colid";
		}

		this.getTableColumns = this.dbConn
				.prepareStatement(this.getTableColumnsStr);
	}

	protected Table getTable(String tableName) throws SQLException {
		this.getTableColumns.setString(1, "[" + this.schema.getName() + "].["
				+ tableName.toLowerCase() + "]");
		ResultSet rs = this.getTableColumns.executeQuery();

		Table table = null;
		String defaultValue = "";
		String colName = "";
		String typeName = "";
		try {
			String tableColumnsFilterList = null;
			String[] arrFilteredColumns = null;
			if ((tableColumnsFilterList = this.schema
					.getTableColumnsFilter(tableName.toLowerCase())) != null) {
				arrFilteredColumns = tableColumnsFilterList.split(",");
			}

			while (rs.next()) {
				if (table == null) {
					table = new Table(this.schema, tableName.toLowerCase(),
							this.targetSchemaName);
				}

				colName = rs.getString("COLUMN_NAME");

				boolean skipCol = false;
				if (arrFilteredColumns != null) {
					for (String filteredColName : arrFilteredColumns) {
						if (colName.equalsIgnoreCase(filteredColName)) {
							skipCol = true;
							break;
						}
					}
				}

				if (skipCol) {
					continue;
				}
				boolean isIdentity = false;

				if (isVersion2005OrGreater())
					isIdentity = rs.getBoolean("is_identity");
				else {
					isIdentity = rs.getString("is_identity").equalsIgnoreCase(
							"YES");
				}

				Column column = new Column(table, colName.toLowerCase());
				typeName = rs.getString("TYPE_NAME").toUpperCase();
				int columnSize = rs.getInt("COLUMN_SIZE");
				defaultValue = rs.getString("COLUMN_DEF");

				if ((defaultValue != null)
						&& (defaultValue.trim().length() > 0)
						&& (defaultValue.startsWith("(("))
						&& (defaultValue.endsWith("))"))) {
					defaultValue = defaultValue.substring(2,
							defaultValue.length() - 2);
				}

				if ((defaultValue != null)
						&& (defaultValue.trim().length() > 0)
						&& (defaultValue.startsWith("("))
						&& (defaultValue.endsWith(")"))) {
					defaultValue = defaultValue.substring(1,
							defaultValue.length() - 1);
				}

				if ((defaultValue != null)
						&& (defaultValue.trim().length() > 0)
						&& (defaultValue.startsWith("'"))
						&& (defaultValue.endsWith("'"))) {
					defaultValue = defaultValue.substring(1,
							defaultValue.length() - 1);
				}

				if ((defaultValue != null)
						&& (defaultValue.equalsIgnoreCase("getdate()"))) {
					defaultValue = "now";
				}

				if ((typeName.equalsIgnoreCase("nvarchar"))
						&& (defaultValue != null)
						&& (defaultValue.trim().length() > 0)
						&& (defaultValue.startsWith("N'"))
						&& (defaultValue.endsWith("'"))) {
					defaultValue = defaultValue.substring(2,
							defaultValue.length() - 1);
				}

				if (((typeName.equalsIgnoreCase("nvarchar")) || (typeName
						.equalsIgnoreCase("nchar"))) && (columnSize > 0)) {
					columnSize /= 2;
				}

				if ((typeName.equalsIgnoreCase("bit"))
						&& (defaultValue != null)
						&& (!defaultValue.equals("0"))
						&& (!defaultValue.equals("1"))) {
					defaultValue = "1";
				}

				if (isIdentity) {
					typeName = typeName + " identity";
				}

				if (MigrationToolkit.getInstance().getTargetDBType() == MTKConstants.DATABASE_TYPE.ENTERPRISEDB)
					typeName = toEDBType(typeName, columnSize);
				else if (MigrationToolkit.getInstance().getTargetDBType() == MTKConstants.DATABASE_TYPE.SRDB) {
					typeName = toPGType(typeName, columnSize);
				}
				column.addDetail(typeName, columnSize, columnSize,
						rs.getInt("DECIMAL_DIGITS"),
						rs.getString("IS_NULLABLE"), isCaseSensitive(colName),
						defaultValue, rs.getString("REMARKS"), null);

				table.addColumn(column);
			}
		} finally {
			if (rs != null) {
				rs.close();
			}
		}
		return table;
	}

	protected void initViewStatement(String commaSepViewNames)
			throws SQLException {
		if (isVersion2005OrGreater()) {
			this.getViewsStr = "select obj.name As view_name,c.text As view_definition  FROM sys.objects obj  INNER JOIN sys.schemas sch ON obj.schema_id=sch.schema_id  INNER JOIN sys.syscomments c ON obj.object_id=c.id  WHERE UPPER(obj.type) = 'V'  AND obj.NAME NOT IN ('sysconstraints', 'syssegments', 'dtproperties', 'sysdiagrams')  AND sch.name = ?";

			if ((commaSepViewNames != null)
					&& (commaSepViewNames.trim().length() > 0)) {
				this.getViewsStr = (this.getViewsStr + " AND obj.name IN ("
						+ commaSepViewNames + ") ");
			}
			this.getViewsStr += " ORDER BY CREATE_DATE";
		} else {
			this.getViewsStr = "select name as view_name,c.text as view_definition from sysobjects obj  INNER JOIN syscomments c ON obj.id=c.id  WHERE UPPER(obj.type) = 'V'  AND obj.NAME NOT IN ('sysconstraints', 'syssegments', 'dtproperties', 'sysdiagrams')  AND user_name(obj.uid) = ? ";

			if ((commaSepViewNames != null)
					&& (commaSepViewNames.trim().length() > 0)) {
				this.getViewsStr = (this.getViewsStr + " AND obj.name IN ("
						+ commaSepViewNames + ") ");
			}
			this.getViewsStr += " ORDER BY CRDATE";
		}
		this.getViews = this.conn.getConnection().prepareStatement(
				this.getViewsStr);
	}

	protected void getViews() throws SQLException {
		writeLog("Getting View Definitions");
		ResultSet rs = null;
		try {
			this.getViews.setString(1, this.schema.getName());
			rs = this.getViews.executeQuery();

			while (rs.next()) {
				View view = new View(rs.getString("VIEW_NAME").toLowerCase(),
						getSchema().getName());

				view.setSQL(rs.getString("view_definition"));
				if (view != null)
					this.schema.addView(view);
			}
		} finally {
			if (rs != null)
				rs.close();
		}
	}

	protected void initConstraintStatement(String commaSepTableNames)
			throws SQLException {
		this.commaSepTableNames = removeSingleQuotes(commaSepTableNames);
	}

	protected void getConstraints() throws SQLException {
		writeLog("Getting Constraint Definitions");
		String tableName = "";
		if ((this.commaSepTableNames != null)
				&& (this.commaSepTableNames.length() > 0)) {
			String[] tableNames = this.commaSepTableNames.split(",");
			for (String name : tableNames)
				getTableConstraints(name);
		} else {
			this.getTables.setString(1, this.dbConn.getCatalog());
			this.getTables.setString(2, this.schema.getName());
			this.getTables.setString(3, "BASE TABLE");
			ResultSet rs = this.getTables.executeQuery();
			try {
				if (rs != null)
					while (rs.next()) {
						tableName = rs.getString("TABLE_NAME");
						getTableConstraints(tableName);
					}
			} finally {
				if (rs != null) {
					rs.close();
				}
			}

		}

		ConstraintList list = this.schema.getConstraints();
		if ((list != null) && (list.size() > 0)) {
			Constraint constraint = null;
			ArrayList cnames = new ArrayList();
			for (int i = 0; i < list.size(); i++) {
				constraint = list.get(i);
				if ((!constraint.getName().equalsIgnoreCase("PRIMARY"))
						&& (!constraint.getName().equalsIgnoreCase(
								"\"PRIMARY\""))
						&& (cnames.contains(constraint.getName()))) {
					constraint.setName(null);
				} else
					cnames.add(constraint.getName());
			}
		}
	}

	private void getTableConstraints(String tableName) throws SQLException {
		Constraint constraint = null;
		Hashtable cache = new Hashtable();
		String pkConstraintName = "";
		String colName = null;
		String primaryKeyStr = "";
		PreparedStatement primaryKey = null;

		if (!isVersion2005OrGreater()) {
			primaryKeyStr = "SELECT sk.name as PK_NAME,so.name TABLE_NAME, sc.name as COLUMN_NAME  FROM syscolumns sc     INNER JOIN sysobjects so ON sc.id = so.id     INNER JOIN sysobjects sk ON sk.parent_obj=so.id and UPPER(sK.xtype)='PK'  WHERE sc.id IN (SELECT [id]                   FROM sysobjects                  WHERE id= so.id)  AND sc.colid IN (SELECT SIK.colid                    FROM sysindexkeys SIK                    JOIN sysobjects SOi ON SIK.[id] = SOi.[id]                    WHERE SIK.indid = 1                     AND SOi.id = so.id)   AND so.id=object_id(?) ORDER BY PK_NAME ASC";
		} else {
			primaryKeyStr = "SELECT i.name AS PK_NAME, c.name AS COLUMN_NAME FROM sys.indexes AS i INNER JOIN sys.index_columns AS ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id INNER JOIN sys.columns AS c ON ic.object_id = c.object_id AND c.column_id = ic.column_id WHERE i.is_primary_key = 1 AND i.object_id = OBJECT_ID(?) ORDER BY PK_NAME, key_ordinal ASC";
		}

		primaryKey = this.dbConn.prepareStatement(primaryKeyStr);
		primaryKey.setString(1, "[" + this.schema.getName() + "]" + "." + "["
				+ tableName + "]");

		ResultSet rs = primaryKey.executeQuery();
		if (rs != null) {
			String pkOriginalName = null;
			String pkName = null;
			try {
				while (rs.next()) {
					pkOriginalName = rs.getString("PK_NAME").toLowerCase();
					pkName = pkOriginalName;
					if (pkOriginalName == null) {
						pkName = "PRIMARY";
					}

					if (!cache.containsKey(pkName)) {
						constraint = new Constraint(
								getTable(tableName.toLowerCase()), pkName,
								isCaseSensitive(pkName));

						constraint.setType(MTKConstants.CONST_PRIMARY);
						cache.put(pkName, constraint);
						this.schema.addConstraint(constraint);
					} else {
						constraint = (Constraint) cache.get(pkName);
					}
					pkConstraintName = pkName;

					colName = rs.getString("COLUMN_NAME").toLowerCase();
					if (isCaseSensitive(colName)) {
						colName = "\"" + colName + "\"";
					}
					constraint.addColumn(new Column(colName));
				}
			} finally {
				if (rs != null)
					rs.close();
			}
		}
		cache.clear();

		String foreignKeyStr = "";
		if (isVersion2005OrGreater()) {
			foreignKeyStr = "SELECT f.name AS FK_NAME, OBJECT_NAME(f.parent_object_id) AS FKTABLE_NAME, COL_NAME(fc.parent_object_id, fc.parent_column_id) AS FKCOLUMN_NAME, OBJECT_NAME (f.referenced_object_id) AS PKTABLE_NAME, COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS PKCOLUMN_NAME ,CASE delete_referential_action_desc WHEN 'CASCADE' THEN 'CASCADE' WHEN 'NO_ACTION' THEN 'NO ACTION' END as DELETE_RULE ,CASE update_referential_action_desc WHEN 'CASCADE' THEN 'CASCADE' WHEN 'NO_ACTION' THEN 'NO ACTION' END as UPDATE_RULE FROM sys.foreign_keys AS f INNER JOIN sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id WHERE is_disabled=0 AND f.parent_object_id = OBJECT_ID(?) ORDER BY FK_NAME";
		} else {
			foreignKeyStr = "SELECT object_name(f.constid) AS FK_NAME, OBJECT_NAME(f.fkeyid) AS FKTABLE_NAME, COL_NAME(f.fkeyid, f.fkey) AS FKCOLUMN_NAME, OBJECT_NAME (f.rkeyid) AS PKTABLE_NAME, COL_NAME(f.rkeyid, f.rkey) AS PKCOLUMN_NAME, CASE objectproperty(f.constid, 'CnstIsDeleteCascade') WHEN 1 THEN 'CASECASE' WHEN 0 THEN 'NO ACTION' END as DELETE_RULE, CASE objectproperty(f.constid, 'CnstIsUpdateCascade') WHEN 1 THEN 'CASECADE' WHEN 0 THEN 'NO ACTION' END as UPDATE_RULE FROM sysforeignkeys AS f WHERE f.fkeyid = OBJECT_ID(?) ORDER BY FK_NAME ";
		}

		PreparedStatement foreignKey = this.dbConn
				.prepareStatement(foreignKeyStr);
		foreignKey.setString(1, "[" + this.schema.getName() + "]" + "." + "["
				+ tableName + "]");

		rs = foreignKey.executeQuery();
		if (rs != null) {
			try {
				String keyName = null;
				String tempTableName = null;
				while (rs.next()) {
					keyName = rs.getString("FK_NAME").toLowerCase();

					if (!cache.containsKey(keyName)) {
						tempTableName = rs.getString("FKTABLE_NAME")
								.toLowerCase();

						constraint = new Constraint(getTable(tempTableName),
								keyName, isCaseSensitive(keyName));

						constraint.setType(MTKConstants.CONST_FOREIGN);
						constraint.setDeleteRule(rs.getString("DELETE_RULE"));

						cache.put(keyName, constraint);
						this.schema.addConstraint(constraint);
					} else {
						constraint = (Constraint) cache.get(keyName);
					}

					colName = rs.getString("FKCOLUMN_NAME").toLowerCase();
					if (isCaseSensitive(colName)) {
						colName = "\"" + colName + "\"";
					}
					constraint.addColumn(new Column(colName));

					colName = rs.getString("PKCOLUMN_NAME").toLowerCase();
					if (isCaseSensitive(colName)) {
						colName = "\"" + colName + "\"";
					}
					constraint.setRefIntegrityTable(rs
							.getString("PKTABLE_NAME").toLowerCase());

					constraint.addRefIntegrityColumn(new Column(colName));
				}
			} finally {
				if (rs != null)
					rs.close();
				if (foreignKey != null)
					foreignKey.close();
			}
		}
		cache.clear();

		if (isVersion2005OrGreater()) {
			this.getConstraintsStr = "SELECT i.name AS CONSTRAINT_NAME, c.name AS COLUMN_NAME FROM sys.indexes AS i INNER JOIN sys.index_columns AS ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id INNER JOIN sys.columns AS c ON ic.object_id = c.object_id AND c.column_id = ic.column_id WHERE i.is_primary_key <> 1 AND is_unique = 1 AND is_unique_constraint = 1 AND i.object_id = OBJECT_ID(?) ORDER BY CONSTRAINT_NAME, key_ordinal ASC";
		} else {
			this.getConstraintsStr = " SELECT so.name as CONSTRAINT_NAME,c.NAME AS COLUMN_NAME from sysobjects so  INNER JOIN sysindexkeys AS ic ON so.parent_obj = ic.id  INNER JOIN syscolumns AS c ON ic.id = c.id AND c.colid = ic.colid  WHERE UPPER(so.xtype)='UQ' AND parent_obj=object_id(?)  ORDER BY CONSTRAINT_NAME, keyno ASC";
		}

		PreparedStatement stmt = this.conn.getConnection().prepareStatement(
				this.getConstraintsStr);
		stmt.setString(1, "[" + this.schema.getName() + "]" + "." + "["
				+ tableName + "]");

		rs = stmt.executeQuery();

		String tempTableName = "";
		if (rs != null) {
			try {
				String keyName = null;
				while (rs.next()) {
					keyName = rs.getString("CONSTRAINT_NAME").toLowerCase();
					if (keyName.equalsIgnoreCase(pkConstraintName))
						continue;
					tempTableName = tableName.toLowerCase();
					colName = rs.getString("COLUMN_NAME").toLowerCase();

					if (!cache.containsKey(keyName)) {
						constraint = new Constraint(getTable(tempTableName),
								keyName, isCaseSensitive(keyName));

						constraint.setType(MTKConstants.CONST_UNIQUE);
						cache.put(keyName, constraint);
						this.schema.addConstraint(constraint);
					} else {
						constraint = (Constraint) cache.get(keyName);
					}

					if (isCaseSensitive(colName)) {
						colName = "\"" + colName + "\"";
					}
					constraint.addColumn(new Column(colName));
				}
			} finally {
				if (rs != null)
					rs.close();
			}
		}
		cache.clear();

		this.getConstraintsStr = "SELECT so.name AS CONSTRAINT_NAME, cols.name as COLUMN_NAME, const.text AS CONSTRAINT_CONDITION FROM syscomments const INNER JOIN sysobjects so ON const.id = so.id INNER JOIN syscolumns cols ON const.colid = cols.colid WHERE cols.id=so.parent_obj AND so.xtype  = 'C' AND so.parent_obj = OBJECT_ID(?)";

		stmt = this.conn.getConnection().prepareStatement(
				this.getConstraintsStr);
		tableName = tableName.toLowerCase();
		stmt.setString(1, "[" + this.schema.getName() + "]" + "." + "["
				+ tableName + "]");

		rs = stmt.executeQuery();

		if (rs != null) {
			try {
				String keyName = null;
				String searchCondition = "";
				String tempOwnerName = this.schema.getName().toLowerCase()
						+ ".";
				while (rs.next()) {
					keyName = rs.getString("CONSTRAINT_NAME").toLowerCase();
					if (!keyName.equalsIgnoreCase(pkConstraintName)) {
						colName = rs.getString("COLUMN_NAME").toLowerCase();
						searchCondition = rs.getString("CONSTRAINT_CONDITION");
						searchCondition = parseCheckConstraintClause(searchCondition);
						searchCondition = searchCondition.replaceAll(
								tempOwnerName, " ");

						if (!cache.containsKey(keyName)) {
							constraint = new Constraint(getTable(tableName),
									keyName, isCaseSensitive(keyName));

							constraint.setType(MTKConstants.CONST_CHECK);
							constraint.setSearchCondition(searchCondition);
							cache.put(keyName, constraint);
							this.schema.addConstraint(constraint);
						} else {
							constraint = (Constraint) cache.get(keyName);
						}

						if (isCaseSensitive(colName)) {
							colName = "\"" + colName + "\"";
						}
						constraint.addColumn(new Column(colName));
					}
				}
			} finally {
				if (rs != null)
					rs.close();
			}
		}
		cache.clear();
		cache = null;
	}

	protected void initIndexeStatement(String commaSepTableNames)
			throws SQLException {
		this.commaSepTableNames = removeSingleQuotes(commaSepTableNames);
	}

	protected void getIndexes() throws SQLException {
		writeLog("Getting Index Definitions");
		if ((this.commaSepTableNames != null)
				&& (this.commaSepTableNames.length() > 0)) {
			String[] tableNames = this.commaSepTableNames.split(",");
			for (String name : tableNames)
				getTableIndexes(name);
		} else {
			this.getTables.setString(1, this.dbConn.getCatalog());
			this.getTables.setString(2, this.schema.getName());
			this.getTables.setString(3, "BASE TABLE");
			ResultSet rs = this.getTables.executeQuery();
			try {
				String tableName = "";
				if (rs != null)
					while (rs.next()) {
						tableName = rs.getString("TABLE_NAME").toLowerCase();
						getTableIndexes(tableName);
					}
			} finally {
				if (rs != null) {
					rs.close();
				}
			}

		}

		IndexList list = this.schema.getIndexes();
		if ((list != null) && (list.size() > 0)) {
			Index index = null;
			String name = null;
			ArrayList indexNames = new ArrayList();
			int[] indexCount = new int[list.size()];

			for (int i = 0; i < list.size(); i++) {
				index = list.get(i);
				name = index.getName();
				if (indexNames.contains(name)) {
					indexCount[indexNames.indexOf(name)] += 1;
					index.setName(name + indexCount[indexNames.indexOf(name)]);
				} else {
					indexNames.add(name);
					indexCount[indexNames.indexOf(name)] = 0;
				}
			}
		}
	}

	private void getTableIndexes(String tableName) throws SQLException {
		Hashtable cache = new Hashtable();
		Index index = null;
		String colName = null;
		Column column = null;
		ResultSet rs = null;

		if (isVersion2005OrGreater()) {
			this.getIndexesStr = "SELECT i.name AS INDEX_NAME, c.name AS COLUMN_NAME, IS_UNIQUE FROM sys.indexes AS i INNER JOIN sys.index_columns AS ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id INNER JOIN sys.columns AS c ON ic.object_id = c.object_id AND c.column_id = ic.column_id WHERE i.is_primary_key <> 1 AND is_unique_constraint <> 1 AND i.object_id = OBJECT_ID(?) ORDER BY INDEX_NAME, key_ordinal ASC";
		} else {
			this.getIndexesStr = "SELECT i.name AS INDEX_NAME, c.name AS COLUMN_NAME, indexproperty(i.id, i.name, 'IsUnique') as IS_UNIQUE FROM sysindexes AS i      INNER JOIN sysindexkeys AS ic         ON i.id = ic.id AND i.indid = ic.indid      INNER JOIN syscolumns AS c         ON ic.id = c.id AND c.colid = ic.colid  WHERE i.id = OBJECT_ID(?)  AND not exists (select 1 from sysconstraints AS sc     join sysobjects AS so         ON so.id = sc.constid AND so.name=i.name     where sc.colid = 0) ORDER BY INDEX_NAME, keyno ASC ";
		}

		this.getIndexes = this.dbConn.prepareStatement(this.getIndexesStr);
		this.getIndexes.setString(1, "[" + this.schema.getName() + "]" + "."
				+ "[" + tableName + "]");

		rs = this.getIndexes.executeQuery();

		if (rs != null) {
			try {
				String indexName = null;
				boolean isUnique = false;
				while (rs.next()) {
					indexName = rs.getString("INDEX_NAME").toLowerCase();
					if (!cache.containsKey(indexName)) {
						index = new Index(getTable(tableName.toLowerCase()),
								indexName);

						if (rs.getString("IS_UNIQUE").equalsIgnoreCase("1"))
							isUnique = true;
						else
							isUnique = false;
						index.setUnique(isUnique);
						cache.put(indexName, index);
						this.schema.addIndex(index);
					} else {
						index = (Index) cache.get(indexName);
					}

					colName = rs.getString("COLUMN_NAME").toLowerCase();
					column = new Column(colName);
					column.setCaseSensitive(isCaseSensitive(colName));
					index.addColumn(column);
				}
			} finally {
				if (rs != null)
					rs.close();
			}
		}
		cache.clear();
		cache = null;
	}

	protected void setConstraintColumnsPSParams(Constraint constraint)
			throws SQLException {
	}

	private String toEDBType(String typeName, int columnSize) {
		if ((typeName.equalsIgnoreCase("varchar(max)"))
				|| (typeName.equalsIgnoreCase("nvarchar(max)"))
				|| ((typeName.equalsIgnoreCase("varchar")) && (columnSize == -1))
				|| ((typeName.equalsIgnoreCase("nvarchar")) && (columnSize == -1))
				|| (typeName.equalsIgnoreCase("ntext"))
				|| (typeName.equalsIgnoreCase("text"))) {
			typeName = "CLOB";
		} else if (typeName.equalsIgnoreCase("nchar"))
			typeName = "CHAR";
		else if (typeName.equalsIgnoreCase("nvarchar"))
			typeName = "VARCHAR";
		else if (typeName.toLowerCase().startsWith("int identity"))
			typeName = "SERIAL";
		else if (typeName.toLowerCase().startsWith("decimal() identity"))
			typeName = "BIGSERIAL";
		else if (typeName.toLowerCase().startsWith("numeric() identity"))
			typeName = "BIGSERIAL";
		else if (typeName.toLowerCase().startsWith("smallint identity"))
			typeName = "SERIAL";
		else if (typeName.toLowerCase().startsWith("bigint identity"))
			typeName = "SERIAL";
		else if (typeName.toLowerCase().startsWith("tinyint identity")) {
			typeName = "SERIAL";
		} else if (typeName.equalsIgnoreCase("SMALLMONEY"))
			typeName = "MONEY";
		else if (typeName.equalsIgnoreCase("IMAGE"))
			typeName = "BYTEA";
		else if (typeName.equalsIgnoreCase("smalldatetime"))
			typeName = "TIMESTAMP";
		else if (typeName.equalsIgnoreCase("DECIMAL")) {
			typeName = "NUMERIC";
		} else if (typeName.equalsIgnoreCase("REAL"))
			typeName = "FLOAT(24)";
		else if (typeName.equalsIgnoreCase("DOUBLE PRECISION"))
			typeName = "FLOAT";
		else if (typeName.equalsIgnoreCase("timestamp")) {
			typeName = "bytea";
		}

		return typeName;
	}

	private String toPGType(String typeName, int columnSize) {
		if ((typeName.equalsIgnoreCase("varchar(max)"))
				|| (typeName.equalsIgnoreCase("nvarchar(max)"))
				|| ((typeName.equalsIgnoreCase("varchar")) && (columnSize == -1))
				|| ((typeName.equalsIgnoreCase("nvarchar")) && (columnSize == -1))
				|| (typeName.equalsIgnoreCase("ntext"))
				|| (typeName.equalsIgnoreCase("text"))) {
			typeName = "text";
		} else if (typeName.equalsIgnoreCase("nchar"))
			typeName = "CHAR";
		else if (typeName.equalsIgnoreCase("nvarchar"))
			typeName = "VARCHAR";
		else if (typeName.toLowerCase().startsWith("int identity"))
			typeName = "SERIAL";
		else if (typeName.toLowerCase().startsWith("decimal() identity"))
			typeName = "BIGSERIAL";
		else if (typeName.toLowerCase().startsWith("numeric() identity"))
			typeName = "BIGSERIAL";
		else if (typeName.toLowerCase().startsWith("smallint identity"))
			typeName = "SERIAL";
		else if (typeName.toLowerCase().startsWith("bigint identity"))
			typeName = "SERIAL";
		else if (typeName.toLowerCase().startsWith("tinyint identity")) {
			typeName = "SERIAL";
		} else if (typeName.equalsIgnoreCase("SMALLMONEY"))
//			typeName = "MONEY";
			typeName="numeric";
		 else if (typeName.equalsIgnoreCase("MONEY"))
				typeName="numeric";
		else if (typeName.equalsIgnoreCase("IMAGE"))
			typeName = "BYTEA";
		else if (typeName.equalsIgnoreCase("smalldatetime"))
			typeName = "TIMESTAMP";
		else if (typeName.equalsIgnoreCase("DECIMAL")) {
			typeName = "NUMERIC";
		} else if (typeName.equalsIgnoreCase("REAL"))
			typeName = "FLOAT(24)";
		else if (typeName.equalsIgnoreCase("DOUBLE PRECISION"))
			typeName = "FLOAT";
		else if (typeName.equalsIgnoreCase("timestamp")) {
			typeName = "bytea";
		}
		// srdb缺少binary类型 2014-10-14
		else if (typeName.equalsIgnoreCase("BINARY")) {
			typeName = "bytea";
		}
		// srdb缺少datetime2(mssql)类型 2014-10-14
		else if (typeName.equalsIgnoreCase("datetime2")) {
			typeName = "TIMESTAMP";
		}
		// srdb缺少datetimeoffset(mssql)类型,与timestamp不兼容 2014-10-14
		else if (typeName.equalsIgnoreCase("datetimeoffset")) {
			typeName = "VARCHAR";
		}
		// srdb缺少hierarchyid(mssql)类型 2014-10-14
		else if (typeName.equalsIgnoreCase("hierarchyid")) {
			typeName = "VARCHAR";
		}
		// srdb time(mssql)类型（jdts不兼容） 2014-10-14
		else if (typeName.equalsIgnoreCase("time")) {
			typeName = "VARCHAR";
		}
		// srdb bit(mssql)类型 2014-10-14
		else if (typeName.equalsIgnoreCase("BIT")) {
			typeName = "BOOLEAN";
		}
		// srdb XML(mssql)类型 2014-10-14
		else if (typeName.equalsIgnoreCase("XML")) {
			typeName = "TEXT";
		}
		return typeName;
	}

	public boolean isCaseSensitive(String identifierName) {
		return !Utility.isValidEDBIdentifier(identifierName);
	}

	public boolean isVersion2005OrGreater() throws SQLException {
		return this.metaData.getDatabaseMajorVersion() >= 9;
	}

	private SQLException processException(SQLException exp) {
		return exp;
	}

	protected static String escape(String s) {
		StringBuffer sb = new StringBuffer();
		int length = s.length();
		for (int i = 0; i < length; i++) {
			char c = s.charAt(i);
			sb.append(c);
			if (c == '\'') {
				sb.append('\'');
			}
			if (c == '\\') {
				sb.append('\\');
			}
		}
		return sb.toString();
	}

	public static String parseCheckConstraintClause(String inputString) {
		StringBuffer result = new StringBuffer();
		boolean quotedString = false;

		for (int i = 0; i < inputString.length() - 1; i++) {
			String currChar = inputString.substring(i, i + 1);
			String nextChar = inputString.substring(i + 1, i + 2);

			if ((!quotedString) && (!currChar.equals("'"))) {
				if ((currChar.equals("[")) || (currChar.equals("]")))
					result.append("\"");
				else
					result.append(currChar.toLowerCase());
			} else if ((!quotedString) && (currChar.equals("'"))) {
				result.append(currChar);
				quotedString = true;
			} else if ((quotedString) && (currChar.equals("'"))
					&& (nextChar.equals("'"))) {
				result.append("''");
				i++;
			} else if ((quotedString) && (currChar.equals("'"))) {
				result.append(currChar);
				quotedString = false;
			} else {
				result.append(currChar);
			}
		}
		result.append(inputString.substring(inputString.length() - 1));
		return result.toString();
	}

	public boolean supportsSynonyms() {
		return false;
	}

	public String getVersion() {
		return "";
	}

	protected void initSynonymStatement(String commaSepSynNames)
			throws SQLException {
		if (isVersion2005OrGreater()) {
			this.getSynonymStr = "select name, base_object_name from sys.synonyms WHERE schema_name(schema_id)= ? ";

			if (commaSepSynNames != null) {
				this.getSynonymStr = (this.getSynonymStr + " AND name IN ("
						+ commaSepSynNames + ")");
			}

			this.getSynonymStr += " ORDER BY name";
			this.getSynonyms = this.conn.getConnection().prepareStatement(
					this.getSynonymStr);
		}
	}

	protected void initAllPublicSynonymStatement() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void initAllPrivateSynonymStatement() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void initSequenceStatement(String commaSepSequenceNames)
			throws SQLException {
	}

	protected void initProcStatement(String commaSepProcNames)
			throws SQLException {
		if (isVersion2005OrGreater()) {
			this.getProcsStr = "select o.name,c.text from sys.objects o INNER JOIN syscomments c ON c.id=o.object_id INNER JOIN sys.schemas sch ON sch.schema_id=o.schema_id where o.type=? and sch.name=?";

			if (commaSepProcNames != null) {
				this.getProcsStr = (this.getProcsStr + " AND o.name IN ("
						+ commaSepProcNames + ") ");
			}
			this.getProcsStr += " ORDER BY  o.create_date";
		} else {
			this.getProcsStr = "select o. name, o.type, c.text from sysobjects o  INNER JOIN syscomments c ON c.id=o.id  and o.type=? and user_name(o.uid)=?";

			if (commaSepProcNames != null) {
				this.getProcsStr = (this.getProcsStr + " AND o.name IN ("
						+ commaSepProcNames + ") ");
			}
			this.getProcsStr += "ORDER BY o.crdate";
		}
		this.getProcs = this.conn.getConnection().prepareStatement(
				this.getProcsStr);
	}

	protected void initPackageStatement(String commaSepPackageNames)
			throws SQLException {
	}

	protected void initTriggerStatement(String commaSepTableNames)
			throws SQLException {
		if (isVersion2005OrGreater()) {
			this.getTriggersStr = "SELECT sys1.name trigger_name, sys2.name table_name,SCHEMA_NAME(tbl.schema_id) schema_name, c.text trigger_body, c.encrypted is_encripted, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1   THEN 0 ELSE 1 END trigger_enabled, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1    THEN 'INSERT' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1    THEN 'UPDATE' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1    THEN 'DELETE' END triggering_event, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1   THEN 'INSTEAD OF' ELSE 'AFTER' END trigger_type FROM sysobjects sys1 JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id JOIN syscomments c ON sys1.id = c.id JOIN sys.tables tbl ON tbl.object_id=sys1.parent_obj WHERE sys1.xtype = 'TR' AND OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') <> 1 AND SCHEMA_ID(?)=tbl.schema_id";

			if (commaSepTableNames != null)
				this.getTriggersStr = (this.getTriggersStr
						+ " AND sys2.name IN (" + commaSepTableNames + ") ");
		} else {
			this.getTriggersStr = "SELECT sys1.name trigger_name,  sys2.name table_name,user_name(sys2.uid) schema_name, c.text trigger_body,  c.encrypted is_encripted, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1   THEN 0 ELSE 1 END trigger_enabled, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1    THEN 'INSERT' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1    THEN 'UPDATE' WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1    THEN 'DELETE' END triggering_event, CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1   THEN 'INSTEAD OF' ELSE 'AFTER' END trigger_type FROM sysobjects sys1 JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id JOIN syscomments c ON sys1.id = c.id WHERE sys1.xtype = 'TR' AND OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') <> 1 AND USER_ID(?)=sys2.uid ";

			if (commaSepTableNames != null) {
				this.getTriggersStr = (this.getTriggersStr
						+ " AND sys2.name IN (" + commaSepTableNames + ") ");
			}
		}

		this.getTriggers = this.conn.getConnection().prepareStatement(
				this.getTriggersStr);
	}

	protected void getPublicSynonyms() throws SQLException {
		if (!isVersion2005OrGreater()) {
			return;
		}
		writeLog("Getting Synonym Definitions");
		ResultSet rs = null;
		try {
			this.getSynonyms.setString(1, this.schema.getName());
			rs = this.getSynonyms.executeQuery();

			while (rs.next()) {
				Synonym ps = new Synonym(getSchema().getName());
				ps.setSynname(rs.getString("name"));
				String tblName = rs.getString("base_object_name");
				if (tblName != null) {
					tblName = tblName.replace("[", "");
					tblName = tblName.replace("]", "");
				}
				ps.setSynobjname(tblName);
				if (ps != null)
					this.schema.addSynonym(ps);
			}
		} finally {
			if (rs != null)
				rs.close();
		}
	}

	protected void getAllPublicSynonyms() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getAllPrivateSynonyms() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getTriggers() throws SQLException {
		writeLog("Getting Trigger Definitions");
		ResultSet rs = null;
		try {
			this.getTriggers.setString(1, this.schema.getName());
			rs = this.getTriggers.executeQuery();

			while (rs.next()) {
				String TriggerName = rs.getString("trigger_name");
				boolean isSimpleTrigName = Utility
						.isValidEDBIdentifier(TriggerName);

				if ((isCaseSensitive(TriggerName)) || (!isSimpleTrigName)) {
					TriggerName = "\"" + TriggerName + "\"";
				}
				Trigger trigger = new Trigger(TriggerName);
				String trigger_body = rs.getString("trigger_body");
				trigger.setDetails(getTable(rs.getString("table_name")),
						rs.getString("trigger_type"),
						rs.getString("triggering_event"));

				trigger.setOwnerName("");
				trigger.setTableOwnerName("");
				trigger.setBody(trigger_body);

				if (trigger != null)
					this.schema.addTrigger(trigger);
			}
		} finally {
			if (rs != null)
				rs.close();
		}
	}

	protected void getSequences() throws SQLException {
	}

	protected void getPackages() throws SQLException {
	}

	protected void getProcedures() throws SQLException {
		writeLog("Getting Procedure Definitions");
		ResultSet rs = null;
		try {
			this.getProcs.setString(1, "P");
			this.getProcs.setString(2, this.schema.getName());
			rs = this.getProcs.executeQuery();
			while (rs.next()) {
				boolean procNameCaseSensitive = isCaseSensitive(rs
						.getString("name"));
				Procedure proc = new Procedure(rs.getString("name"), null,
						procNameCaseSensitive);
				proc.setSQL(rs.getString("text"));

				ProcedureList pl = this.schema.getProcedures();
				boolean updated = false;
				for (int i = pl.size() - 1; i >= 0; i--) {
					if (pl.get(i).getFullName().equals(proc.getFullName())) {
						pl.get(i).setSQL(proc.getSQL());
						updated = true;
						break;
					}
				}
				if (!updated)
					this.schema.addProcedure(proc);
			}
		} finally {
			if (rs != null)
				rs.close();
		}
	}

	protected void getFunctions() throws SQLException {
		writeLog("Getting Function Definitions");
		ResultSet rs = null;
		try {
			this.getProcs.setString(1, "FN");
			this.getProcs.setString(2, this.schema.getName());
			rs = this.getProcs.executeQuery();
			while (rs.next()) {
				Function func = new Function(rs.getString("name"), null);
				func.setSQL(rs.getString("text"));

				FunctionList fl = this.schema.getFunctions();
				boolean updated = false;
				for (int i = fl.size() - 1; i >= 0; i--) {
					if (fl.get(i).getFullName().equals(func.getFullName())) {
						fl.get(i).setSQL(func.getSQL());
						updated = true;
						break;
					}
				}
				if (!updated)
					this.schema.addFunction(func);
			}
		} finally {
			if (rs != null)
				rs.close();
		}
	}

	public void executeScript(String sql) throws SQLException {
		Statement stmt = null;
		try {
			if (sql.compareTo("") != 0) {
				stmt = this.dbConn.createStatement();

				String[] arrSQL = sql.split(SQL_STATEMENT_DELIMITER);

				for (int i = 0; i < arrSQL.length; i++)
					stmt.execute(arrSQL[i]);
			}
		} finally {
			if (stmt != null)
				stmt.close();
		}
	}

	public boolean schemaExists(String schemaName) throws SQLException {
		boolean schemaFlag = false;
		ResultSet rs = null;
		String schemaQuery = null;
		PreparedStatement schema = null;

		schemaQuery = "SELECT SCHEMA_NAME(schema_id) FROM sys.schemas ";

		schema = this.dbConn.prepareStatement(schemaQuery);
		try {
			rs = schema.executeQuery();

			while (rs.next()) {
				if (rs.getString(1).equalsIgnoreCase(schemaName))
					schemaFlag = true;
			}
		} finally {
			if (rs != null) {
				rs.close();
			}

			if (schema != null) {
				schema.close();
			}
		}

		return schemaFlag;
	}

	public void dropTableConstsAndIndexes(
			MTKConstants.DATABASE_TYPE sourceDBType, Table table)
			throws SQLException {
		dropTableConsts(sourceDBType, table, true, true, true, true);

		// dropTableIndexesDefs(table, sourceDBType ==
		// MTKConstants.DATABASE_TYPE.SQLSERVER);
	}

	// public void dropTableConsts(MTKConstants.DATABASE_TYPE sourceDBType,
	// Table table, MTKConstants.TABLE_CONSTRAINT_TYPE constType)
	// throws SQLException
	// {
	// switch
	// (1.$SwitchMap$com$edb$common$MTKConstants$TABLE_CONSTRAINT_TYPE[constType.ordinal()])
	// {
	// case 1:
	// dropTableConsts(sourceDBType, table, true, false, false, false);
	// break;
	// case 2:
	// dropTableConsts(sourceDBType, table, false, true, false, false);
	// break;
	// case 3:
	// dropTableConsts(sourceDBType, table, false, false, true, false);
	// break;
	// case 4:
	// dropTableConsts(sourceDBType, table, false, false, false, true);
	// }
	// }

	protected void dropTableConsts(MTKConstants.DATABASE_TYPE sourceDBType,
			Table table, boolean dropPKConst, boolean dropCKConst,
			boolean dropFKConst, boolean dropUniqueConst) throws SQLException {
		ResultSet rs = null;
		try {
			if (this.psConsts == null)
				this.psConsts = this.conn
						.getConnection()
						.prepareStatement(
								"SELECT OBJECT_NAME(OBJECT_ID) AS NameofConstraint, type AS ConstraintType FROM sys.objects WHERE type_desc LIKE '%CONSTRAINT'  and SCHEMA_NAME(schema_id) = ? and OBJECT_NAME(parent_object_id) = ? ");
			else {
				this.psConsts.clearParameters();
			}

			this.psConsts.setString(1,
					Utility.removeEnclosingQuotes(table.getTargetSchemaName()));
			this.psConsts
					.setString(2, Utility.removeEnclosingQuotes(table
							.getEDBCompatibleName()));
			rs = this.psConsts.executeQuery();

			while (rs.next()) {
				String constName = rs.getString(1);
				String constType = rs.getString(2).trim();

				if (isCaseSensitive(constName)) {
					constName = "\"" + constName + "\"";
				}

				if (constType.equalsIgnoreCase("C")) {
					table.setHasCheckConst(true);
				}

				if (((constType.equalsIgnoreCase("PK")) && (!dropPKConst))
						|| ((constType.equalsIgnoreCase("F")) && (!dropFKConst))
						|| ((constType.equalsIgnoreCase("C")) && (!dropCKConst))
						|| ((constType.equalsIgnoreCase("UQ")) && (!dropUniqueConst))) {
					continue;
				}

				executeScript("ALTER TABLE "
						+ table.getTargetSchemaFullyQualifiedName(sourceDBType,
								MTKConstants.DATABASE_TYPE.ENTERPRISEDB, false)
						+ " DROP CONSTRAINT " + constName);
			}
		} finally {
			if (rs != null)
				rs.close();
		}
	}

	// protected ArrayList<String> dropTableIndexesDefs(Table table, boolean
	// createBackup)
	// throws SQLException
	// {
	// ResultSet rs = null;
	//
	// if (createBackup) {
	// this.listTableIndexesDefs.clear();
	// }
	//
	// try
	// {
	// if (this.psIndexesDefs == null)
	// this.psIndexesDefs =
	// this.conn.getConnection().prepareStatement("select I.name as IndexName, I.type_desc as IndexType  from sys.tables as T inner  join sys.indexes as I on T.[object_id] = I.[object_id]  inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]  inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]  inner join sys.objects as so on t.object_id = so.object_id and I.object_id = T.object_id  where SCHEMA_NAME(so.schema_id) = ?  and   so.name = ? ");
	// else {
	// this.psIndexesDefs.clearParameters();
	// }
	//
	// this.psIndexesDefs.setString(1,
	// Utility.removeEnclosingQuotes(table.getTargetSchemaName()));
	// this.psIndexesDefs.setString(2,
	// Utility.removeEnclosingQuotes(table.getEDBCompatibleName()));
	// rs = this.psIndexesDefs.executeQuery();
	//
	// String tempTargetSchemaName = table.getTargetSchemaName();
	// if (isCaseSensitive(tempTargetSchemaName)) {
	// tempTargetSchemaName = "\"" + tempTargetSchemaName + "\"";
	// }
	//
	// while (rs.next()) {
	// indexName = rs.getString(1);
	//
	// if (createBackup) {
	// this.listTableIndexesDefs.add(rs.getString(2));
	// }
	//
	// if (isCaseSensitive(indexName)) {
	// indexName = "\"" + indexName + "\"";
	// }
	//
	// executeScript("DROP INDEX " + indexName + " ON " + tempTargetSchemaName +
	// "." + table.getName());
	// }
	//
	// if ((createBackup) && (this.listTableIndexesDefs.size() > 0))
	// {
	// this.mapTableIndexesDefs.put(table.getTargetSchemaQualifiedName(),
	// this.listTableIndexesDefs);
	// }
	//
	// indexName = this.listTableIndexesDefs;
	// }
	// finally
	// {
	// String indexName;
	// if (rs != null)
	// rs.close();
	// }
	// }

	public String[] getSchemas() throws SQLException {
		throw new UnsupportedOperationException(
				"Schemas are not supported yet.");
	}

	protected void initDBLinkStatement() throws SQLException {
		throw new UnsupportedOperationException("DB Links are not supported.");
	}

	protected void getDBLinks() throws SQLException {
		throw new UnsupportedOperationException("DB Links are not supported.");
	}

	protected void getRoles() throws SQLException {
		throw new UnsupportedOperationException("Roles are not supported yet.");
	}

	protected void getUsers() throws SQLException {
		throw new UnsupportedOperationException("Users are not supported yet.");
	}

	protected void initRoleStatement(String commaSepRoleNames)
			throws SQLException {
		throw new UnsupportedOperationException("Roles are not supported yet.");
	}

	protected void initUserStatement(String commaSepUserNames)
			throws SQLException {
		throw new UnsupportedOperationException("Users are not supported yet.");
	}

	protected void initGrantStatement(String commaSepUserNames)
			throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getGrants() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	public int getDBServerMajorVersion() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	public int getDBServerMinorVersion() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void initRulesStatement(String commaSepRuleNames)
			throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getRules() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void initGroupsStatement(String commaSepGroupNames)
			throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getGroups() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	public String getDatabaseName() {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void initDomainsStatement(String commaSepDomainNames)
			throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getDomains() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void initCustomDataTypesStatement(String commaSepTypes)
			throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	protected void getCustomDataTypes() throws SQLException {
		throw new UnsupportedOperationException("Not supported yet.");
	}

	@Override
	public void parseTables() throws SQLException {
		// TODO Auto-generated method stub

	}

	@Override
	public String getParseTablesMsg() throws SQLException {
		return null;
	}
}

/*

 */